<template>
  <div>
    <router-view v-slot="{ Component }">
      <!-- 
        因为不同的name会执行不同的动画效果
        当我们进入一个新页面的时候，name变成push执行新页面跳转动画
        当我们返回一个旧页面的时候，name变成back执行返回动画
     -->
      <transition
        @before-enter="beforeEnter"
        @after-enter="afterEnter"
        :name="transitionName"
      >
        <!-- include控制缓存组件是一个数组，数组中的元素是组件名称 -->
        <keep-alive :include="virtualTaskStack">
          <component :is="Component" />
        </keep-alive>
      </transition>
    </router-view>
  </div>
</template>

<script>
const ROUTER_TYPE_PUSH = "push";
const ROUTER_TYPE_BACK = "back";
const NONE = "none";
const ROUTER_TYPE_ENUM = [ROUTER_TYPE_PUSH, ROUTER_TYPE_BACK, NONE];
// 为什么要定义一个数组
// 因为要做成一个通用的组件，判断你当前的组件使用是否正确
</script>

<script setup>
import { defineProps, ref } from "vue";
import { useRouter } from "vue-router";
import { useStore } from "vuex";
const store = useStore();

let transitionName = ref("");
let router = useRouter();
//在路由守卫中设置动画名称
router.beforeEach((to, name) => {
  const iconActive = ["Home", "Cart", "Order", "Mine"];
  let index = iconActive.findIndex((ele) => ele == to.name);
  store.state.index = index;

  let bool = iconActive.some((ele) => ele == to.name);
  store.state.showDocker = bool;

  // to是即将跳转的目的路由
  const toPath = virtualTaskStack.value.findIndex((ele) => ele == to.name);
  const fromPath = virtualTaskStack.value.findIndex((ele) => ele == name.name);
  transitionName.value = toPath > fromPath ? "push" : "back";
  // console.log(transitionName.value);
  // 进栈出栈操作  【home,my】  my
  if (transitionName.value === ROUTER_TYPE_PUSH) {
    // 进栈的操作
    virtualTaskStack.value.push(to.name);
  } else if (transitionName.value === ROUTER_TYPE_BACK) {
    // 出栈的操作
    virtualTaskStack.value.pop();
  }
  if (to.name === props.mainComponentName) {
    // 跳回首页 清空任务栈的操作=>就是把数组重置
    clearTask();
  }
});

// 需要做一个标记，标记新页面 要执行push动画
// 需要另外的一个标记，表明你是返回旧页面，执行back动画
let props = defineProps({
  // 如果routerType push back
  // 路由跳转的类型：push是进入组件 back是推出组件
  // routerType: {
  //   type: String,
  //   default: NONE,
  //   validator(val) {
  //     // 如果我们在设置跳转的过程中没有设置push 或者back提示开发者，你要设置
  //     // 保证开发者一定要传递这个routerType,且routerType是push或者back或者none
  //     const result = ROUTER_TYPE_ENUM.includes(val);
  //     if (!result) {
  //       // routerType的值不是push back none 三者之一，提示错误信息
  //       // 抛出异常
  //       throw new Error(`你的router_type必须是ROUTER_TYPE_ENUM的其中之一`);
  //     }
  //     return result;
  //   },
  // },
  //  接受显示的组件
  mainComponentName: {
    type: String,
    required: true,
  },
});

// isAimate 控制动画执行
let isAnimate = ref(false);
const beforeEnter = () => {
  // console.log(beforeEnter);
  isAnimate.value = true;
};
const afterEnter = () => {
  // console.log(afterEnter);
  isAnimate.value = false;
};

// 初始化空的任务栈 =>先把首页放在初始化数组中
let virtualTaskStack = ref([props.mainComponentName]);
// 定义重置的任务栈方法
const clearTask = () => {
  virtualTaskStack.value = [props.mainComponentName];
};
</script>

<style lang="scss" scoped>
// push页面时：新页面的进入动画
.push-enter-active {
  animation-name: push-in;
  animation-duration: 0.3s;
}
// push页面时：老页面的退出动画
.push-leave-active {
  animation-name: push-out;
  animation-duration: 0.3s;
}
// push页面时：新页面的进入动画
@keyframes push-in {
  0% {
    transform: translate(100%, 0);
  }
  100% {
    transform: translate(0, 0);
  }
}
// push页面时：老页面的退出动画
@keyframes push-out {
  0% {
    transform: translate(0, 0);
  }
  100% {
    transform: translate(-100%, 0);
  }
}

// 后退页面时：即将展示的页面动画
.back-enter-active {
  animation-name: back-in;
  animation-duration: 0.4s;
}
// 后退页面时：后退的页面执行的动画
.back-leave-active {
  animation-name: back-out;
  animation-duration: 0.4s;
}
// 后退页面时：即将展示的页面动画
@keyframes back-in {
  0% {
    width: 100%;
    transform: translate(-100%, 0);
  }
  100% {
    width: 100%;
    transform: translate(0, 0);
  }
}
// 后退页面时：后退的页面执行的动画
@keyframes back-out {
  0% {
    width: 100%;
    transform: translate(0, 0);
  }
  100% {
    width: 100%;
    transform: translate(100%, 0);
  }
}
</style>
